package com.remote.common.context;

import com.remote.common.DefaultRemoteFactory;
import com.remote.common.RemoteConfiguration;
import com.remote.common.RemoteFactory;
import com.remote.common.RemoteHandlerRegister;
import com.remote.common.command.Commands;
import com.remote.common.command.handler.ICommandHandler;
import com.remote.common.context.listener.CloseListener;
import com.remote.common.context.listener.ConnectListener;
import com.remote.common.context.listener.ReadListener;
import com.remote.common.exception.RemoteException;
import com.remote.common.model.ServerClientInfo;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;

public abstract class AbstractRemoteContext implements RemoteContext, RemoteFactory, RemoteHandlerRegister {

    private RemoteFactory remoteFactory;
    private ChannelInitializer<SocketChannel> channelInitializer;
    private Class<?> decoderClass;
    private Class<?> encoderClass;
    private ChannelHandler channelHandler;
    private List<ReadListener> readListeners;
    private List<CloseListener> closeListeners;
    private List<ConnectListener> connectListeners;
    private boolean isInit = false;

    public AbstractRemoteContext(RemoteConfiguration remoteConfiguration) {
        this(new DefaultRemoteFactory(remoteConfiguration));
    }

    public AbstractRemoteContext(RemoteFactory remoteFactory) {
        this.remoteFactory = remoteFactory;
        this.readListeners = new ArrayList<>();
        this.closeListeners = new ArrayList<>();
        this.connectListeners = new ArrayList<>();
    }

    @Override
    public void addCloseListener(CloseListener closeListener) {
        this.closeListeners.add(closeListener);
    }

    @Override
    public void addConnectListener(ConnectListener connectListener) {
        this.connectListeners.add(connectListener);
    }

    @Override
    public void addReadListener(ReadListener<?> readListener) {
        this.readListeners.add(readListener);
    }

    @Override
    public void setDecoderClass(Class<?> decoderClass) {
        this.decoderClass = decoderClass;
    }

    @Override
    public void setEncoderClass(Class<?> encoderClass) {
        this.encoderClass = encoderClass;
    }

    @Override
    public void setChannelHandler(ChannelHandler channelHandler) {
        this.channelHandler = channelHandler;
    }


    @Override
    public void setChannelInitializer(ChannelInitializer<SocketChannel> channelInitializer) {
        this.channelInitializer = channelInitializer;
    }

    @Override
    public synchronized Channel connect() throws RemoteException {
        if (!isInit) {//没有初始化就加载引导
            this.initBootstrap();
            this.isInit = true;
        }
        if (this.channelInitializer instanceof RemoteHandlerRegister) {//注册通道初始化需要的东西
            RemoteHandlerRegister remoteReaderRegister = (RemoteHandlerRegister) channelInitializer;
            remoteReaderRegister.setDecoderClass(this.decoderClass);
            remoteReaderRegister.setEncoderClass(this.encoderClass);
            remoteReaderRegister.setChannelHandler(this.channelHandler);
        }
        return this.onConnect();
    }

    protected abstract Channel onConnect();

    protected abstract void initBootstrap();


    @Override
    public RemoteFactory getRemoteFactory() {
        return remoteFactory;
    }

    @Override
    public void registerHandler(Enum<Commands> commandsEnum, ICommandHandler commandHandler) {
        remoteFactory.registerHandler(commandsEnum, commandHandler);
    }

    @Override
    public ServerClientInfo getClient(String clientId) throws RemoteException {
        return remoteFactory.getClient(clientId);
    }

    @Override
    public void addClient(ServerClientInfo clientInfo) throws RemoteException {
        remoteFactory.addClient(clientInfo);
    }

    @Override
    public boolean hasClient(String controlClient) {
        return remoteFactory.hasClient(controlClient);
    }

    @Override
    public void removeClient(String controlClient) {
        remoteFactory.removeClient(controlClient);
    }

    @Override
    public ICommandHandler getCommandHandler(Enum<Commands> commandsEnum) {
        return remoteFactory.getCommandHandler(commandsEnum);
    }

    @Override
    public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) {
        remoteFactory.setScheduledExecutorService(scheduledExecutorService);
    }

    @Override
    public RemoteConfiguration getRemoteConfiguration() {
        return remoteFactory.getRemoteConfiguration();
    }

    @Override
    public String generateClientId() {
        return remoteFactory.generateClientId();
    }

    @Override
    public List<CloseListener> getCloseListeners() {
        return closeListeners;
    }

    @Override
    public List<ReadListener> getReadListeners() {
        return readListeners;
    }

    @Override
    public List<ConnectListener> getConnectListeners() {
        return connectListeners;
    }

    public ChannelInitializer<SocketChannel> getChannelInitializer() {
        return channelInitializer;
    }

    public Class<?> getDecoderClass() {
        return decoderClass;
    }

    public Class<?> getEncoderClass() {
        return encoderClass;
    }

    public ChannelHandler getChannelHandler() {
        return channelHandler;
    }


}
